//
//  BusInterface.h
//  sad
//
//  Created by Christopher Kemsley on 2/23/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef sad_BusInterface_h
#define sad_BusInterface_h

#include "SystemCDefinitions.hpp"


#define	BusNamespaceBegin	namespace Bus {
#define	BusNamespaceEnd		}


BusNamespaceBegin



typedef unsigned	Address ;
typedef unsigned	Identifier ;
typedef unsigned	Length ;

Address const		AddressMax	=	(~((Address)0)) ;
Address const		LengthMax	=	(~((Length)0)) ;


enum {
	kOperationWrite		=	1 ,
	kOperationRead		=	0
} ;
typedef unsigned	Operation ;


Address		uniqueAddress	( void* pointer ) ;





// This structure acts like a unsigned int limited to 32-bits on 32- and 64-bit
// systems. You may also access individual bytes from within the word.
/*struct	Word
{
	Word	() ;
	Word	( Word const & copy ) ;
	Word	( unsigned const & value ) ;
	~Word	() ;
	
	// These let us act like an unsigned value
	operator unsigned () const ;
	Word&	operator=	( Word const & copy ) ;
	Word&	operator=	( unsigned const & value ) ;
	
	// These let us act like a byte array
	unsigned char&	operator[]	( unsigned byteIndex ) ;
	
private:
	unsigned mValue ; // big enough for >=32-bit systems
} ;*/
typedef SystemC::UInt32		Word ;




// This structure encodes the necessary request data. Note that only information
// actually part of the request is contained - not sender IDs.
struct	Request
{
	Request		() ;
	Request		( Request const & copy ) ;
	Request		( Address const & inAddress , Operation const & inOperation , Length const & inBlockLength=1 ) ;
	~Request	() ;
	
	Address		baseAddress ;
	Operation	operation ;
	Length		blockLength ;
	
	bool		isValid () const ;
	void		invalidate () ;
	
	void		operator= ( Request const & copy ) ;
	
	bool		operator== ( Request const & compare ) const ;
	
	
	friend std::ostream& operator<< ( std::ostream & stream , Request const & request ) ;
	
	// Don't touch this
	unsigned	uniqueID ;
};




// This defines the abstract interface for masters to interface with busses.
// Note that all methods may be blocking, so they should always be called from a thread.
class	MasterInterface : virtual public sc_interface
{
public:
	virtual void	request		( Identifier const & inSender , Request const & inRequest ) = 0 ;
	virtual bool	waitForAcknowledge	( Identifier const & sender ) = 0 ;
	
	virtual void	readWord	( Word & word ) = 0 ;
	virtual void	writeWord	( Word const & word ) = 0 ;
} ;



// This defines the abstract interface for slaves to interface with busses.
// Note that all methods may be blocking, so they should always be called from a thread.
class	SlaveInterface : virtual public sc_interface
{
public:
	virtual void	waitForNewRequest	( Request & outRequest ) = 0 ;
	virtual void	acknowledgeRequest	() = 0 ;
	
	virtual void	readWord	( Word & word ) = 0 ;
	virtual void	writeWord	( Word const & word ) = 0 ;
} ;





// This performs synchronous read/write on the pipe. That is, writes will wait until the value
// is read and reads will wait until a value is written. Multiple, unfulfilled RWs will result
// in an exception.
struct	Pipe
{
	Pipe () ;
	~Pipe () ;
	
	void	read	( Word & word ) ;
	void	write	( Word const & word ) ;
	
private:
	Word		mValue ;
	bool		mIsValid ;
	sc_event	mWasRead ;
	sc_event	mWasWritten ;
	unsigned	mReaderCount ; // for debugging
	unsigned	mWriterCount ; // for debugging
} ;



BusNamespaceEnd





#endif
